<?php
// $id$
/**
 * 应用程序的公共控制器基础类
 *
 * 可以在这个类中添加方法来完成应用程序控制器共享的功能。
 */
abstract class Controller_Abstract extends QController_Abstract
{
    /**
     * 控制器动作要渲染的数据
     *
     * @var array
     */
    protected $_view = array();

    /// cached_actions 需要缓存的动作。派生类在初始化的时候设置。
    protected $_cached_actions = array();

    /**
     * 控制器要使用的视图类
     *
     * @var string
     */
    protected $_view_class = 'RenderSmarty';

    /**
     * 控制器要使用的视图
     *
     * @var string
     */
    protected $_viewname = null;

    /**
     * 控制器所属的应用程序
     *
     * @var CommunityApp
     */
    protected $_app;

    /**
     * 构造函数
     */
    function __construct($app)
    {
        parent::__construct();
        $this->_app = $app;
    }

    /**
     * 执行指定的动作
     *
     * @return mixed
     */
    function execute($action_name, array $args = array())
    {

        $action_method = "action{$action_name}";
        $mustCached = in_array($action_name, $this->_cached_actions);

        $config = $this->loadSmartyConfig($mustCached);
        $response = new $this->_view_class($config);
        $response->setViewname($this->_getViewName());

        // 调用用户级别的方法执行指定的动作方法
        $this->_before_execute();

        // 当前动作如果属于可以缓存的操作，则优先判断是否已经缓存。
        // 如果已经缓存则直接读取内容返回，否则按照常规的方式进行内容生成。

        if ( $mustCached ) {
            $context = QContext::instance();

            // 如果已经缓存了内容，则直接返回缓存的内容。
            if ($response->isCached($context['cache_id'])) {

                #IFDEF DBEUG
                QLog::log('EXECUTE ACTION CACHED: '. get_class($this) . '::' . $action_method . '()', QLog::DEBUG);
                #ENDIF

                return $response;
            }

        }

        #IFDEF DBEUG
        QLog::log('EXECUTE ACTION: '. get_class($this) . '::' . $action_method . '()', QLog::DEBUG);
        #ENDIF

        $ret = call_user_func_array(array($this, $action_method), $args);
        $this->_after_execute($ret);

        if (is_null($ret) && is_array($this->_view))
        {
            $response->assign($this->_view);
            $this->_before_render($response);
        }

        return is_string($ret) ? $ret : $response;
    }

    /**
     * 指定的控制器动作未定义时调用
     *
     * @param string $action_name
     */
    function _on_action_not_defined($action_name)
    {
    }

    function _before_execute()
    {
    }

    function _after_execute()
    {
    }

	/// 固定的输出内容部分。
    function _before_render(& $response)
    {
        $response->assign('header', $this->getHeader());
        $response->assign('footer',  $this->getFooter());
    }


    /**
     * 准备视图目录，如果存在用户级别的模版，指向该模版目录，否则指向系统自带的模版目录。
     *
     * @return array
     */
    protected function _getViewDir()
    {
        if ($this->_context->module_name)
        {
            // 如果指向的是扩展模块，则视图模版在该模块的view目录下。
            $dir = Q::ini('app_config/MODULE_DIR') . "/{$this->_context->module_name}/view";
        }
        else
        {
            // 否则指向应用的view目录
            $dir = Q::ini('app_config/APP_DIR') . '/view';
        }

        if ($this->_context->namespace)
        {
            $dir .= "/{$this->_context->namespace}";
        }

        return $dir;
    }

    /**
     * 确定要使用的视图
     *
     * @return string
     */
    protected function _getViewName()
    {
        if ($this->_viewname === false)
        {
            return false;
        }

         $viewname = empty($this->_viewname) ? $this->_context->action_name : $this->_viewname;
         return strtolower("{$this->_context->controller_name}/{$viewname}");
    }

    /**
     * 显示一个提示页面，然后重定向浏览器到新地址
     *
     * @param string $caption
     * @param string $message
     * @param string $url
     * @param int $delay
     * @param string $script
     *
     * @return QView_Render_PHP
     */
    protected function _redirectMessage($caption, $message, $url, $delay = 5, $script = '')
    {
        $config = $this->loadSmartyConfig();

        $response = new $this->_view_class($config);
        $response->setViewname('redirect_message');
        $response->assign(array(
            'message_caption'       => $caption,
            'message_body'          => $message,
            'redirect_url'          => $url,
            'redirect_delay'        => $delay,
            'hidden_script'         => $script,
        ));

        return $response;
    }

    /**
    *    loadSmartyConfig
    *    载入smarty相关的运行参数。
    **   @param  void
    *    @return array
    *    @access public
    */
    function loadSmartyConfig( $useCache = false ) {

        $options = array('template_dir', 'compile_dir','config_dir','plugins_dir', 'debugging','error_reporting','compile_check','force_compile','caching','cache_dir','cache_lifetime','cache_modified_check','left_delimiter','right_delimiter','use_sub_dirs','file_extname');

        $ret = array('view_dir' => $this->_getViewDir());

        foreach ($options as $op){
            $value = Q::ini('smarty_' . $op);
            if (!is_null($value)) {
                $ret[$op] = $value;
            }
        }

        // 如果不可以缓存，自动清除缓存的方式。否则按照参数设置的缓存方式进行缓存。
        if ($useCache == false) {
            unset($ret['caching']);
        }

        return $ret;
    }




    /**
     *     获得页面的头内容。
     *     包括title，meta，站点css和script
     **   @param  void
     *    @return  html
     *    @access public
     */
    protected function getHeader() {
        return "<title>{$this->_view['page_title']}</title>";
    }



    /**
     *    获取页脚版权信息。
     *
     **   @param  (object objecttype|type) [$varname] [description]
     *    @return void
     *    @access public
     */
    protected function getFooter() {
        return "<div id='footer'>由 <a href='http://sites.google.com/site/braceletshop/' target='_blank' >Bracelet</a> 网店引擎强力驱动 </div>";
    }

}




